/*
 * File Name:               CLocalTimer.cs
 *
 * Description:             本地计时器
 * *                        针对暂停情况可以分别创建两个Timer
 * Author:                  lisiyu <576603306@qq.com>
 * Create Date:             2016/11/18
 */

using System;
using System.Collections.Generic;

public class XLocalTimer
{
    private float mCurrentTime;

    private List<CDelayTimer> mDelayWaits;
    private List<CDelayTimer> mDelayTimers;

    private List<CIntervalTimer> mIntervalWaits;
    private List<CIntervalTimer> mIntervalTimers;

    private List<ulong> mCancels;

    public XLocalTimer(int capacity)
    {
        mCurrentTime = 0;
        mDelayWaits = new List<CDelayTimer>(capacity);
        mDelayTimers = new List<CDelayTimer>(capacity);
        mIntervalWaits = new List<CIntervalTimer>(capacity);
        mIntervalTimers = new List<CIntervalTimer>(capacity);
        mCancels = new List<ulong>(capacity);
    }

    public void delayCall(ulong uid, float delayTime, Action<object> callback, object args)
    {
        var timer = XCachePool.Singleton.pop<CDelayTimer>(args);
        timer.pCallback = callback;
        timer.pUid = uid;
        timer.pExcuteTime = mCurrentTime + delayTime;

        mDelayWaits.Add(timer);
    }

    public void intervalCall(ulong uid, float intervalTime, Action<object> callback, object args)
    {
        var timer = XCachePool.Singleton.pop<CIntervalTimer>(args);
        timer.pCallback = callback;
        timer.pUid = uid;
        timer.pExcuteTime = mCurrentTime + intervalTime;
        timer.pIntervalTime = intervalTime;

        mIntervalWaits.Add(timer);
    }

    public void cancelCall(ulong uid)
    {
        mCancels.Add(uid);
    }

    public void onUpdate(float deltaTime)
    {
        mCurrentTime += deltaTime;

        updateDelay();
        updateInterval();
    }

    private void updateDelay()
    {
        //         if (mDelayWaits.Count > 0)
        //         {
        //             mDelayTimers.AddRange(mDelayWaits);
        //             //mDelayTimers.Sort();
        //         }

        //int count = 0;
        var needClear = false;
        for (int i = 0; i < mDelayWaits.Count; ++i)
        {
            var timer = mDelayWaits[i];
            if (mCurrentTime < timer.pExcuteTime)
                continue;

            if (mCancels.Contains(timer.pUid))
            {
                mCancels.Remove(timer.pUid);
            }
            else
            {
                timer.excute();
                XCachePool.Singleton.push(timer);
                needClear |= true;
            }

            //count++;
        }

        if (needClear)
            mDelayWaits.RemoveAll(t => !t.alive);
        //          mDelayTimers.Clear();
        //         for (int i = 0; i < count; i++)
        //         {
        //             mDelayTimers.RemoveAt(i);
        //         }
    }

    private void updateInterval()
    {
        if (mIntervalWaits.Count > 0)
        {
            mIntervalTimers.AddRange(mIntervalWaits);
        }

        for (int i = mIntervalTimers.Count - 1; i >= 0; i--)
        {
            var timer = mIntervalTimers[i];
            if (mCurrentTime < timer.pExcuteTime)
                continue;

            if (mCancels.Contains(timer.pUid))
            {
                mCancels.Remove(timer.pUid);
                mIntervalTimers.Remove(timer);
            }
            else
            {
                timer.excute();
            }
        }
    }
}